// ES6 提供了新的数据结构 Set。它类似于数组，但是成员的值都是唯一的，没有重复的值。
// Set本身是一个构造函数，用来生成 Set 数据结构。
const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
    console.log(i);
}
// 2 3 5 4
let array = [1, 2, 2, 3, 3, 4]
// 去除数组的重复成员
console.log([...new Set(array)])
//上面的方法也可以用于，去除字符串里面的重复字符。
console.log([...new Set('ababbc')].join(''))//abc
/*
向 Set 加入值的时候，不会发生类型转换，所以5和"5"是两个不同的值。
Set 内部判断两个值是否不同，使用的算法叫做“Same-value-zero equality”，
它类似于精确相等运算符（===），主要的区别是向 Set 加入值时认为NaN等于自身，而精确相等运算符认为NaN不等于自身
*/
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
console.log(set) // Set(1) {NaN}
// 两个对象总是不相等的
let set2 = new Set()
set2.add({});
console.log(set2.size) // 1

set2.add({});
console.log(set2.size) // 2
// Array.from()方法可以将 Set 结构转为数组。
const items = new Set([1, 2, 3, 4, 5]);
const array2 = Array.from(items);
const array3 = [...items]
console.log(typeof array3) //Object
console.log(array3) //[ 1, 2, 3, 4, 5 ]
/*
keys方法、values方法、entries方法返回的都是遍历器对象
由于 Set 结构没有键名，只有键值（或者说键名和键值是同一个值），所以keys方法和values方法的行为完全一致。
*/
let set4 = new Set(['red', 'green', 'blue']);

for (let item of set4.keys()) {
    console.log(item);
}
// red
// green
// blue

for (let item of set4.values()) {
    console.log(item);
}
// red
// green
// blue

for (let item of set4.entries()) {
    console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
// let arr = [1, 2, 3, 4, 5];
// let x;
// for (let i = 0; i < arr.length; i++) {
//     x = i - 2 > 0 ? i - 2 : 0;
//     console.log(x)
// }

//遍历的应用
//扩展运算符（...）内部使用for...of循环，所以也可以用于 Set 结构。
let set5 = new Set(['red', 'green', 'blue']);
let arr = [...set5];
console.log('arr:', arr)

//扩展运算符和 Set 结构相结合，就可以去除数组的重复成员。
let arr1 = [3, 5, 2, 2, 5, 5];
let unique = [...new Set(arr1)];
// [3, 5, 2]

//数组的map和filter方法也可以间接用于 Set 
set = new Set([1, 2, 3]);
set = new Set([...set].map(x => x * 2));
// 返回Set结构：{2, 4, 6}

set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(x => (x % 2) == 0));
// 返回Set结构：{2, 4}

//交并集
let aa = new Set([1, 2, 3]);
let bb = new Set([4, 3, 2]);

// 并集
let union = new Set([...aa, ...bb]);
// Set {1, 2, 3, 4}

// 交集
let intersect = new Set([...aa].filter(x => bb.has(x)));
// set {2, 3}

// （a 相对于 b 的）差集
let difference = new Set([...aa].filter(x => !bb.has(x)));
// Set {1}


//同步改变原来的set
let set6 = new Set([1, 2, 3]);
set = new Set([...set6].map(val => val * 2));
// set的值是2, 4, 6

// 方法二
let set7 = new Set([1, 2, 3]);
set = new Set(Array.from(set7, val => val * 2));